<?php
/**
 * Created by PhpStorm.
 * User: meng
 * Date: 2021/7/6
 * Time: 2:37 下午
 */

namespace app\admin\model;


use app\lib\exception\BadRequestException;
use app\utils\EncryptUtils;
use app\utils\JwtUtils;
use Carbon\Carbon;
use Gregwar\Captcha\CaptchaBuilder;
use Ramsey\Uuid\Uuid;
use think\db\Query;
use think\facade\Cache;
use think\model\concern\SoftDelete;
use think\Paginator;

class AdminUserModel extends AdminBaseModel
{
    use SoftDelete;

    protected $table = 'admin_user';

    protected $deleteTime = 'delete_time';
    protected $hidden = ['password', 'delete_time'];

    const NOT_FOUND = 20000;
    const PASSWORD = 20001;
    const BLACK_LIST = 20002;
    const CREATE_FAIL = 20003;
    const UPDATE_FAIL = 20004;
    const IDENTICAL_PASS = 20005;
    const DELETE_FAIL = 20006;

    protected static $allowedFields = [
        'create' => ['username', 'nickname', 'mobile', 'avatar', 'gender', 'email', 'password', 'introduction', 'create_time'],
        'update' => ['nickname', 'mobile', 'avatar', 'gender', 'email', 'password', 'introduction', 'last_login_ip', 'status', 'last_login_time']
    ];

    public static function userInfo ($userid) {
        // 获取用户信息
        $user = self::findUser($userid);
        // 获取用户角色信息
        $roles = AdminRoleModel::where('id', 'in', function (Query $query) use ($userid) {
            $query->table('admin_role_user')->where('user_id', $userid)->field('role_id');
        })->field('id, name')->select()->toArray();
        // 获取用户菜单信息
        $roleIds = array_column($roles, 'id');
        if (in_array(1, $roleIds)) { // 如果角色中有超级管理员
            $menus = AdminMenuModel::select();
        } else {
            $menus = AdminMenuModel::where('id', 'in', function (Query $query) use ($roleIds) {
                $query->table('admin_role_menu')->where('role_id', 'in', $roleIds)->field('menu_id');
            })->select();
        }
        $user['roles'] = $roles;
        $user['menus'] = $menus;
        return $user;
    }

    public static function createUser ($params) {
        $params['password'] = EncryptUtils::passowrdEncrypt($params['password']);
        $params['create_time'] = (string)Carbon::now();
        self::create($params, self::$allowedFields['create']);
    }

    public static function updateUser ($id, $params) {
        $user = self::findUser($id);
        if (isset($params['password'])) {
            unset($params['password']);
        }
        $user->allowField(self::$allowedFields['update'])->save($params);
    }

    public static function deleteUser ($id) {
        $user = self::findUser($id);
        $user->delete();
    }

    public static function login ($params): array {
        $user = self::where('username', $params['username'])->find();
        if (empty($user)) {
            $user = self::where('mobile', $params['username'])->find();
        }
        if (empty($user)) {
            throw new BadRequestException(self::NOT_FOUND);
        }
        if ($user['status'] == 2) {
            throw new BadRequestException(self::BLACK_LIST);
        }
        if (EncryptUtils::passowrdEncrypt($params['password']) != $user['password']) {
            throw new BadRequestException(self::PASSWORD);
        }
        $user->save(['last_login_time' => (string)Carbon::now()]);
        return (new JwtUtils())->awardToken($user['id']);
    }

    public static function findUser ($id) {
        $user = self::find($id);
        if (empty($user)) {
            throw new BadRequestException(self::NOT_FOUND);
        }
        return $user;
    }

    public static function getUserList ($params): Paginator {
        $where = self::queryWhere($params);
        return self::where($where)
            ->order(self::querySort($params))
            ->with(['roles'])
            ->paginate(self::queryLimit($params));
    }

    public function roles () {
        return $this->hasMany(AdminRoleUserModel::class, 'user_id', 'id');
    }

    public static function queryWhere ($params): array {
        $where = [];
        if (!empty($params['keyword'])) {
            $where[] = ['username|mobile', 'like', '%' . trim($params['keyword']) . '%'];
        }
        if (isset($params['gender']) && in_array(intval($params['gender']), [0, 1, 2])) {
            $where[] = ['gender', '=', intval($params['gender'])];
        }
        if (isset($params['status']) && in_array(intval($params['status']), [1, 2])) {
            $where[] = ['status', '=', intval($params['status'])];
        }
        return $where;
    }

    public static function createCaptcha (): array {
        $token = (string)Uuid::uuid4();
        $builder = new CaptchaBuilder();
        $builder->build();
        $codeUrl = $builder->inline();
        $codeText = $builder->getPhrase();
        $cacheData = [
            'code'  => $codeText,
            'times' => 0
        ];
        Cache::store('redis')->set($token, $cacheData, 300);
        return [
            'token' => $token,
            'code' => $codeUrl
        ];
    }
}
